package org.yelongframework.excel.poi.workbook;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.yelongframework.excel.ExcelException;
import org.yelongframework.excel.poi.sheet.DefaultPOIExcelSheet;
import org.yelongframework.excel.sheet.ExcelSheet;
import org.yelongframework.excel.workbook.AbstractExcelWorkbook;
import org.yelongframework.poi.POIExcelSupport;

/**
 * 抽象实现
 * 
 * @since 1.0.0
 */
public abstract class AbstractPOIExcelWorkbook extends AbstractExcelWorkbook implements POIExcelWorkbook {

	/** POI工作薄支持 */
	private final POIExcelSupport poiExcelSupport;

	// ==================================================构造器==================================================

	/**
	 * @param workbook        工作表
	 * @param poiExcelSupport Excel支持
	 */
	public AbstractPOIExcelWorkbook(Workbook workbook, POIExcelSupport poiExcelSupport) {
		super(workbook);
		this.poiExcelSupport = Objects.requireNonNull(poiExcelSupport, "poiExcelSupport");
	}

	// ==================================================工作表数量==================================================

	@Override
	public int getSheetNum() {
		return getWorkbook().getNumberOfSheets();
	}

	// ==================================================创建工作表==================================================

	@Override
	public ExcelSheet createSheet(String sheetName) {
		Sheet sheet = getWorkbook().createSheet(sheetName);
		return new DefaultPOIExcelSheet(this, sheet);
	}

	// ==================================================获取工作表==================================================

	@Override
	public ExcelSheet getSheet(int index) {
		Workbook workbook = getWorkbook();
		try {
			Sheet sheet = workbook.getSheetAt(index);
			return null == sheet ? null : new DefaultPOIExcelSheet(this, sheet);
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public List<ExcelSheet> getSheetList() {
		int numberOfSheets = getWorkbook().getNumberOfSheets();
		List<ExcelSheet> poiExcelSheetList = new ArrayList<>(numberOfSheets);
		for (int i = 0; i < numberOfSheets; i++) {
			poiExcelSheetList.add(getSheet(i));
		}
		return poiExcelSheetList;
	}

	// ==================================================获取工作表索引==================================================

	@Override
	public int getSheetIndex(ExcelSheet sheet) {
		Object srcSheet = sheet.getSheet();
		return srcSheet instanceof Sheet ? getWorkbook().getSheetIndex((Sheet) srcSheet) : -1;
	}

	// ==================================================复制工作表==================================================

	@Override
	public void copySheet(int srcSheetIndex, int destSheetIndex) {
		ExcelSheet srcSheet = getSheet(srcSheetIndex);
		if (null == srcSheet) {
			throw new ExcelException("复制失败，源Sheet索引【" + srcSheetIndex + "】的Sheet不存在。");
		}
		ExcelSheet destSheet = getSheet(destSheetIndex);
		if (null == destSheet) {
			int sheetNum = getSheetNum();
			if (sheetNum > destSheetIndex) {
				throw new ExcelException("目标Sheet【" + destSheetIndex + "】不存在且无法创建");
			}
			for (int i = sheetNum + 1; i <= destSheetIndex + 1; i++) {
				createSheet(i + "");
			}
			destSheet = getSheet(destSheetIndex);
		}
		copySheet(srcSheet, destSheet);
	}

	@Override
	public void copySheet(ExcelSheet srcSheet, ExcelSheet destSheet) {
		getPOIExcelSupport().copySheet(getWorkbook(), (Sheet) srcSheet.getSheet(), (Sheet) destSheet.getSheet());
	}

	// ==================================================写入到流中==================================================

	@Override
	public void write(OutputStream outputStream) throws IOException {
		getWorkbook().write(outputStream);
	}

	// ==================================================工作薄==================================================

	@Override
	public Workbook getWorkbook() {
		return (Workbook) super.getWorkbook();
	}

	// ==================================================支持==================================================

	@Override
	public POIExcelSupport getPOIExcelSupport() {
		return poiExcelSupport;
	}

}
